#-*- coding: utf-8 -*-

__all__ = ['format_opt_to_varname',
           'container_to_cli', 'parse_container_cli',
           'CliRunner']

import argparse
from pyLot.application import APPLICATION
from pyLot.core import ENCODING, make_alias, isimplementation
from .interfaces.api import ICli, ICliModifier, ICliSimpleModifier

class CliRunner(object):
  def __init__(self, args, namespace, level, parents=None, add_help=False):
    self.ext_point_id = 'pyLot.cli.modifiers_%s' % level
    if parents is None :
      parents = []
    parser = argparse.ArgumentParser(add_help=add_help, parents=parents)
    climodifier = None
    climodifiers = []
    pm = APPLICATION.getPluginManager()
    for climodifier_class in pm.get_extensions(self.ext_point_id) :
      try :
        climodifier = climodifier_class(parser)
      except argparse.ArgumentError, e:
        if APPLICATION.DEBUG_PLUGINS :
          raise e
      else :
        climodifiers.append(climodifier)
    namespace, args = parser.parse_known_args(args, namespace)

    if isimplementation(climodifier, ICliModifier) :
      self.clitype = ICliModifier
      def parse_before ():
        for climodifier in climodifiers :
          climodifier.parseBefore(namespace)

      def parse_class (target):
        for climodifier in climodifiers :
          climodifier.parseClass(namespace, target)

      def parse_instance (target):
        for climodifier in climodifiers :
          climodifier.parseInstance(namespace, target)

      def parse_after (target):
        for climodifier in climodifiers :
          climodifier.parseAfter(namespace, target)

      def parse_stop ():
        for climodifier in climodifiers :
          climodifier.parseStop(namespace)

      self.parse_before = parse_before
      self.parse_class = parse_class
      self.parse_stop = parse_stop
      self.parse_instance = parse_instance
      self.parse_after = parse_after

    elif isimplementation(climodifier, ICliSimpleModifier) :
      self.clitype = ICliSimpleModifier
      def parse_target(target):
        for climodifier in climodifiers :
          climodifier.parseTarget(namespace, target)
      for attrib in ('parse_before', 'parse_stop', 'parse_after',
                     'parse_class', 'parse_instance', 'parse'):
        setattr(self, attrib, self._null)

    elif isimplementation(climodifier, ICli) :
      self.clitype = ICli
      def parse():
        for climodifier in climodifiers :
          climodifier.parse(namespace)
      for attrib in ('parse_before', 'parse_stop', 'parse_after',
                     'parse_class', 'parse_instance', 'parse_target'):
        setattr(self, attrib, self._null)
      self.parse = parse

    else :
      self.clitype = None
      for attrib in ('parse_before', 'parse_stop', 'parse_after', 'parse',
                     'parse_class', 'parse_instance', 'parse_target'):
        setattr(self, attrib, self._null)

    self.namespace = namespace
    self.args = args
    self.parser = parser
    self.climodifiers = climodifiers

  def _null (self, *args, **kargs):
    pass

  def run(self, factory, *args, **kargs):
    self.parse_before()
    self.parse_class(factory)
    obj = factory(*args, **kargs)
    self.parse_instance(obj)
    self.parse_after(obj)
    return obj

def format_opt_to_varname(string):
  """
  génère un nom de variable compatible python à partir d'une option de 
  ligne de commande
  
  >>> format_opt_to_varname('--install-dir')
  'install_dir'
  """
  if string.startswith('--') :
    string = string[2:]
  return string.replace('-', '_')

def container_to_cli(parser_or_group, container, skip_container_name=False,
                     tr_=tr_):
#  from pyLot.core import Container
#  container = Container()
  for path in container.walkDatum():
    datum = container[path]
    if skip_container_name :
      path = u'/'.join(path.split(u'/')[1:])
    if datum.tooltip :
      _help = u'%s. %s' % (tr_(make_alias(datum)), tr_(datum.tooltip))
    else :
      _help = tr_(make_alias(datum))
    _help = _help.encode(ENCODING)
    arg_name = str(path.replace(u'/', u'-'))
    arg_dest = str(path.replace(u'/', u'_'))
    if datum.nature == unicode :
      if datum.value is None :
        metavar = str(datum.name)
        default = None
      else :
        metavar = datum.value.encode(ENCODING)
        default = metavar
      action = parser_or_group.add_argument('--%s' % arg_name,
        action='store', dest=arg_dest, metavar=metavar, help=_help,
        default=default)
    elif datum.nature in (int, float):
      if datum.value is None :
        metavar = str(datum.name)
      else :
        metavar = str(datum.value)
      action = parser_or_group.add_argument('--%s' % arg_name,
        action='store', dest=arg_dest, default=datum.value,
        metavar=metavar, help=_help)
    else :
      continue

def parse_container_cli(namespace, container, skip_container_name=False):
  for path in container.walkDatum():
    datum = container[path]
    if skip_container_name :
      path = u'/'.join(path.split(u'/')[1:])

    arg_dest = str(path.replace(u'/', u'_'))
    try :
      value = getattr(namespace, arg_dest)
    except AttributeError :
      continue
    else :
      if datum.nature in (unicode, int, float) :
        datum.value = str(value).decode(ENCODING)
